
package com.mybatis.generator;

import com.mybatis.generator.core.*;
import com.mybatis.generator.db.DbUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


public class GeneratorUtils {

    public static void main(String[] args) throws Exception {
        runner();
    }

    private static Context context = null;

    public static void runner() throws Exception {

        initContext();

        for (Table table : context.getTables()) {
            if (table.getPrimaryKey() == null
                    || table.getPrimaryKey().getJdbcType() == null) {
                System.out.println("表`" + table.getTableName() + "`,没有找到主键，跳过处理！");
                continue;
            }
            DomainGenerator.process(context, table);
            MapperGenerator.process(context, table);
            ServiceGenerator.process(context, table);
            SqlMapGenerator.process(context, table);
            VoGenerator.process(context, table);
            DtoGenerator.process(context, table);
        }

        System.out.println("========bye bye!=========");

    }

    public static void initContext() throws Exception {
        //TODO 修改为本地环境地址，还有generatorConfig.xml 文件中对应的各类的目录，还有cofig目录下的三个properties文件中数据库配置
        //File config = new File("D:\\serverSpace\\ProjectSpace\\YGFL\\YGFL-Server\\hc-parent\\hc-generator\\src\\main\\resources\\generatorConfig.xml");
//        File config = new File("D:\\serverSpace\\ProjectSpace\\eee\\YGFL-Server\\hc-parent\\hc-generator\\src\\main\\resources\\generatorConfig.xml");
        File config = new File("/Users/yjl/YjdService/YGFL-Server/hc-parent/hc-generator/src/main/resources/generatorConfig.xml");
        if (!config.exists()) {
            throw new Exception(
                    "没有找到配置文件：src/main/resources/generatorConfig.xml");
        }
        SAXReader reader = new SAXReader();
        Document document = reader.read(config);
        Element root = document.getRootElement();

        context = new Context();

        context.setSchema(root.attributeValue("schema"));

        jdbcConection(root, context);
        javaTypeResolver(root, context);

        context.setMapper(root.element("mapper").attributeValue("value"));
        context.setVo(root.element("vo").attributeValue("value"));
        context.setDto(root.element("dto").attributeValue("value"));
        context.setSqlmap(root.element("sqlmap").attributeValue("value"));

        parseTables(root, context);

        setColumns(context);

    }

    /**
     * @param ctx
     * @throws Exception void
     * @date 2015年12月19日 下午7:28:59
     */
    public static void setColumns(Context ctx) throws Exception {
        for (Table table : ctx.getTables()) {
            List<Column> columns = DbUtils.getColumns(ctx,
                    table.getTableName());
            table.setColumns(columns);
            for (Column column : columns) {
                column.setPropertyName(JavaBeanUtils
                        .getCamelCaseString(column.getName(), false));
                column.setJdbcType(ctx.getJavaTypeResolver()
                        .getProperty(column.getDataType()));
                if (table.getColumnOverids() != null) {
                    String jdbcType = table.getColumnOverids().getProperty(
                            column.getDataType(), ctx.getJavaTypeResolver()
                                    .getProperty(column.getDataType()));
                    if (jdbcType == null || "".equals(jdbcType)) {
                        jdbcType = "Object";
                    }
                    column.setJdbcType(jdbcType);
                }
                if (table.getPrimaryKey() != null) {
                    if (column.getName()
                            .equals(table.getPrimaryKey().getColumnName())) {
                        table.getPrimaryKey().setJdbcType(column.getJdbcType());
                        table.getPrimaryKey()
                                .setPropertyName(column.getPropertyName());
                        column.setPrimaryKey(true);
                    }
                }
            }
        }
    }

    public static void jdbcConection(Element root, Context ctx)
            throws Exception {
        Element jdbcConection = root.element("jdbcConnection");
        if (jdbcConection == null) {
            throw new Exception("没有找到jdbcConection节点");
        }
        String driverClass = jdbcConection.attributeValue("driverClass");
        if (driverClass == null) {
            throw new Exception("没有找到jdbcConection节点的driverClass属性或为空");
        }
        String connectionURL = jdbcConection.attributeValue("connectionURL");
        if (connectionURL == null) {
            throw new Exception("没有找到jdbcConection节点的connectionURL属性或为空");
        }
        String uName = jdbcConection.attributeValue("uName");
        if (uName == null) {
            throw new Exception("没有找到jdbcConection节点的uName属性或为空");
        }
        String password = jdbcConection.attributeValue("password");
        if (password == null) {
            throw new Exception("没有找到jdbcConection节点的password属性或为空");
        }
        Properties properties = new Properties();
        properties.put("driverClass", driverClass);
        properties.put("connectionURL", connectionURL);
        properties.put("uName", uName);
        properties.put("password", password);
        ctx.setJdbcProperties(properties);
    }

    public static void javaTypeResolver(Element root, Context ctx)
            throws Exception {
        List nodes = root.selectNodes("//context/javaTypeResolver/property");
        Properties properties = new Properties();
        for (Object object : nodes) {
            Element property = (Element) object;
            properties.put(property.attributeValue("name"),
                    property.attributeValue("value"));
        }
        ctx.setJavaTypeResolver(properties);
    }

    public static void parseTables(Element root, Context ctx) throws Exception {
        List tablesElement = root.elements("table");
        List<Table> tables = new ArrayList<Table>();
        Table table = null;
        for (Object object : tablesElement) {
            Element tableElement = (Element) object;
            table = new Table();
            String tableName = tableElement.attributeValue("tableName");
            if (tableName == null || "".equals(tableName)) {
                throw new Exception("表名为空");
            }
            String prefix = tableElement.attributeValue("prefix");
            if (prefix != null && !"".equals(prefix)) {
                tableName = tableName.replace(prefix, "");
            }
            table.setTableName(tableElement.attributeValue("tableName"));

            String mapperName = tableElement.attributeValue("mapperName");
            if (mapperName == null || "".equals(mapperName)) {
                mapperName = JavaBeanUtils.getCamelCaseString(tableName, true)
                        + "Mapper";
            }
            table.setMapperName(mapperName);
            table.setMapperAnName(JavaBeanUtils.firstLowerCase(mapperName));

            String domainName = tableElement.attributeValue("domainObjectName");
            if (domainName == null || "".equals(domainName)) {
                domainName = JavaBeanUtils.getCamelCaseString(tableName, true);
            }
            table.setDomainObjectName(domainName);

            String sqlmapName = tableElement.attributeValue("sqlmapName");
            if (sqlmapName == null || "".equals(sqlmapName)) {
                sqlmapName = mapperName;
            }
            table.setSqlMapperName(sqlmapName);

            String serviceName = tableElement.attributeValue("serviceName");
            if (serviceName == null || "".equals(serviceName)) {
                serviceName = JavaBeanUtils.getCamelCaseString(tableName, true)
                        + "Service";
            }
            table.setServiceName(serviceName);
            table.setServiceAnName(JavaBeanUtils.firstLowerCase(serviceName));
            String packageName = tableElement.attributeValue("packageName");
            if (packageName == null || "".equals(packageName)) {
                throw new Exception("包名不能为空");
            }
            table.setPackageName(packageName);
            table.setPrefix(prefix);
            // 主键
            Element generatedKeyElement = tableElement.element("generatedKey");
            if (generatedKeyElement == null) {
                throw new Exception("没有找到generatedKey节点");
            }
            String primaryKeyName = generatedKeyElement
                    .attributeValue("column");
            boolean bool = "true"
                    .equals(generatedKeyElement.attributeValue("identity"));
            table.setPrimaryKey(new PrimariKey(primaryKeyName, bool));
            String voShortName = generatedKeyElement.attributeValue("name");
            String voName = generatedKeyElement.attributeValue("packageName");
            if (voShortName != null && voShortName != null
                    && ctx.getVo() != null) {
                table.setVo(new Vo(voShortName, voName));
            }

            if (voShortName != null && voShortName != null
                    && ctx.getDto() != null) {
                table.setDto(new Dto(voShortName, voName));
            }

            // 数据类型重写
            Properties properties = new Properties();
            List columnOveridsElement = tableElement.elements("columnOverid");
            for (Object obj : columnOveridsElement) {
                Element columnOverid = (Element) obj;
                properties.put(columnOverid.attributeValue("name"),
                        columnOverid.attributeValue("javaType"));
            }
            table.setColumnOverids(properties);

            Element voElment = tableElement.element("vo");
            if (voElment != null) {
                table.setVo(new Vo(voElment.attributeValue("name"),
                        voElment.attributeValue("packageName")));
            }

            Element dtoElment = tableElement.element("dto");
            if (dtoElment != null) {
                table.setDto(new Dto(dtoElment.attributeValue("name"),
                        dtoElment.attributeValue("packageName")));
            }

            String desc = tableElement.attributeValue("desc");
            if (desc != null && !"".equals(desc)) {
                table.setDesc(desc);
            }
            tables.add(table);
        }
        ctx.setTables(tables);
    }

}
